library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ─────────────────────────────────── tidyverse 1.3.1 ──
✔ ggplot2 3.3.6     ✔ purrr   0.3.4
✔ tibble  3.1.7     ✔ dplyr   1.0.9
✔ tidyr   1.2.0     ✔ stringr 1.4.0
✔ readr   2.1.2     ✔ forcats 0.5.1
── Conflicts ────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
library(scales)

Attaching package: ‘scales’

The following object is masked from ‘package:purrr’:

    discard

The following object is masked from ‘package:readr’:

    col_factor
library(plotly)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
library(lubridate)

Attaching package: ‘lubridate’

The following objects are masked from ‘package:base’:

    date, intersect, setdiff, union

Covid Tab

#loads in beds and add year column
beds <- read_csv("raw_data/non_covid_raw_data/beds_by_nhs_board_of_treatment_and_specialty.csv") %>% janitor::clean_names()

beds %>% 
mutate(date = yq(quarter),
         year = year(date))
# bed percentage availablity for "all acute"
# Will need to add filter for year based on user input
beds_plotly <- beds %>%
  filter(specialty_name == "All Acute") %>% 
  group_by(quarter, specialty_name) %>%
  summarise(mean_perc_occ = mean(percentage_occupancy)) %>% 
  ggplot(aes(x = quarter, y = mean_perc_occ))+
  geom_line(aes(colour = specialty_name, group = specialty_name))+
  geom_point(size = 0.5)+
  theme(axis.text.x = element_text(angle = 90, hjust = 1))+
  labs(title = "Mean bed availability for all Acute Patients",
       x = "\nYear and Quarter",
       y = "Average Percentage Occupancy")
`summarise()` has grouped output by 'quarter'. You can override using the `.groups` argument.
ggplotly(beds_plotly) %>% config(displayModeBar = FALSE)
NA
NA

Scotland Shapefile

ae_wait_times wrangling

ae_wait_times <- read_csv("raw_data/non_covid_raw_data/monthly_ae_waitingtimes_202206.csv") %>% janitor::clean_names()
Rows: 15837 Columns: 25── Column specification ──────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (13): Country, HBT, TreatmentLocation, DepartmentType, NumberOfAttendancesEpisodeQF, N...
dbl (12): Month, NumberOfAttendancesAggregate, NumberOfAttendancesEpisode, NumberMeetingTa...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#glimpse(ae_wait_times)


#make a date and year column with the first date of every month
ae_wait_times <- ae_wait_times %>% 
  mutate(date = ym(month), .after = month,
         year = year(date))

#make a percent column with percent of patients meeting the 4hr target time
ae_wait_times <- ae_wait_times %>% 
  mutate(percent_4hr_target_achieved = (number_meeting_target_aggregate/number_of_attendances_aggregate)*100)

target_2007 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2007) %>% 
  rename(ae_target_2007 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2007)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2008 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2008) %>% 
  rename(ae_target_2008 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2008)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2009 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2009) %>% 
  rename(ae_target_2009 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2009)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2010 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2010) %>% 
  rename(ae_target_2010 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2010)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2011 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2011) %>% 
  rename(ae_target_2011 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2011)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2012 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2012) %>% 
  rename(ae_target_2012 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2012)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2013 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2013) %>% 
  rename(ae_target_2013 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2013)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2014 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2014) %>% 
  rename(ae_target_2014 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2014)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2015 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2015) %>% 
  rename(ae_target_2015 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2015)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2016 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2016) %>% 
  rename(ae_target_2016 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2016)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2017 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2017) %>% 
  rename(ae_target_2017 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2017)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2018 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2018) %>% 
  rename(ae_target_2018 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2018)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2019 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2019) %>% 
  rename(ae_target_2019 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2019)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2020 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2020) %>% 
  rename(ae_target_2020 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2020)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
target_2021 <- ae_wait_times %>%
  group_by(year, hbt) %>% 
  summarise(ae_4hr_target_achieved = mean(percent_4hr_target_achieved, na.rm = TRUE)) %>% 
  filter(year == 2021) %>% 
  rename(ae_target_2021 = ae_4hr_target_achieved) %>% 
  ungroup() %>% 
  select(hbt,ae_target_2021)
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
  

shape file wrangling

scotland <- st_read("../SG_NHS_HealthBoards_2019_shapefile/SG_NHS_HealthBoards_2019.shp")
Reading layer `SG_NHS_HealthBoards_2019' from data source 
  `C:\Users\neilp\Documents\CODECLAN\phs_scotland_group_project\SG_NHS_HealthBoards_2019_shapefile\SG_NHS_HealthBoards_2019.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 14 features and 4 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 5512.998 ymin: 530250.8 xmax: 470332 ymax: 1220302
Projected CRS: OSGB 1936 / British National Grid
# make a smaller version for performance issues
scotland_smaller <- scotland %>% 
  st_simplify(TRUE, dTolerance = 2000)
#fixes problems caused by above 
scotland_smaller <- sf::st_cast(scotland_smaller, "MULTIPOLYGON")

#add in the A&E 4 hr target data for each year
scotland_smaller <-  scotland_smaller %>% 
  mutate(centres = st_centroid(st_make_valid(geometry))) %>%
    mutate(lat = st_coordinates(centres)[,1],
           long = st_coordinates(centres)[,2],
           target_2007 = target_2007$ae_target_2007,
           target_2008 = target_2008$ae_target_2008,
           target_2009 = target_2009$ae_target_2009,
           target_2010 = target_2010$ae_target_2010,
           target_2011 = target_2011$ae_target_2011,
           target_2012 = target_2012$ae_target_2012,
           target_2013 = target_2013$ae_target_2013,
           target_2014 = target_2014$ae_target_2014,
           target_2015 = target_2015$ae_target_2015,
           target_2016 = target_2016$ae_target_2016,
           target_2017 = target_2017$ae_target_2017,
           target_2018 = target_2018$ae_target_2018,
           target_2019 = target_2019$ae_target_2019,
           target_2020 = target_2020$ae_target_2020,
           target_2021 = target_2021$ae_target_2021
                  )


# This will require filtered by the year selected in the dashboard
# Can we get the button or dropdown to pass eg "target_2016" to this in 2 places?
p <- ggplot(scotland_smaller) + 
  geom_sf(aes(fill = target_2021, 
              text = paste("<b>", HBName, "</b>\n", round(target_2021, digits = 2),"%", sep = ""))) + 
  scale_fill_viridis_c(option = "plasma", name = "4Hr A&E Target %")+
  theme_void()+
  labs(title = "Percent of A&E depts making the 4hr target")
Warning: Ignoring unknown aesthetics: text
p %>%
  ggplotly(tooltip = "text") %>%
  style(hoverlabel = list(bgcolor = "white"), hoveron = "fill")%>% 
  config(displayModeBar = FALSE)

SIMD graph

simd <- read_csv("raw_data/non_covid_raw_data/inpatient_and_daycase_by_nhs_board_of_treatment_and_simd.csv") %>% janitor::clean_names()
# average episodes by SIMD value
# currently unfiltered for health board or admission type etc
simd_plotly <- simd %>% 
  drop_na(simd) %>%
  mutate(simd = as.factor(simd)) %>% # gives each simd a separate colour
  group_by(quarter, simd) %>% 
  summarise(avg_episodes = mean(episodes, na.rm = TRUE)) %>% 
  ggplot(aes(x = quarter, y = avg_episodes, group = simd))+
  geom_line(aes(colour = simd))+
  geom_point(size = 0.5)+
  scale_y_continuous(labels = scales::comma)+
  labs(title = "Average Hospital Episodes by SIMD Deprevation score\n",
       x = "\nYear and Quarter",
       y = "Average Episodes\n")+
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))
`summarise()` has grouped output by 'quarter'. You can override using the `.groups` argument.
ggplotly(simd_plotly)

Age Graph

age_sex <- read_csv("raw_data/non_covid_raw_data/inpatient_and_daycase_by_nhs_board_of_treatment_age_and_sex.csv") %>% janitor::clean_names()


 # age_sex <-  age_sex %>% 
 #    mutate(quarter = yq(quarter))
# Average number of episode for age groups
# currently unfiltered by department or anything else
age_plotly <- age_sex %>% 
  group_by(quarter, age) %>% 
  summarise(avg_episodes = mean(episodes, na.rm = TRUE)) %>% 
  ggplot(aes(x = quarter, y = avg_episodes))+
  geom_line(aes(colour = age, group = age))+ 
  geom_point(size = 0.5)+
  labs(title = "Average Hospital Episodes by Age Groups\n",
       x = "\nYear and Quarter",
       y = "Average Episodes\n")+
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))
`summarise()` has grouped output by 'quarter'. You can override using the `.groups` argument.
  
ggplotly(age_plotly)

Gender

sex_plotly <- age_sex %>% 
  group_by(quarter, sex) %>% 
  summarise(avg_length_of_episode = mean(average_length_of_episode, na.rm = TRUE)) %>% 
  ggplot(aes(x = quarter, y = avg_length_of_episode))+
  geom_line(aes(colour = sex, group = sex))+
  #geom_smooth(aes(colour = sex, group = sex), se = FALSE)+
  geom_point(size = 0.5)+
  labs(title = "Average Hospital Episodes by Gender\n",
       x = "\nYear and Quarter",
       y = "Average Episodes\n")+
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))
`summarise()` has grouped output by 'quarter'. You can override using the `.groups` argument.
ggplotly(sex_plotly)
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoc2YpDQpgYGANCg0KDQoNCiMjIENvdmlkIFRhYg0KYGBge3J9DQojbG9hZHMgaW4gYmVkcyBhbmQgYWRkIHllYXIgY29sdW1uDQpiZWRzIDwtIHJlYWRfY3N2KCJyYXdfZGF0YS9ub25fY292aWRfcmF3X2RhdGEvYmVkc19ieV9uaHNfYm9hcmRfb2ZfdHJlYXRtZW50X2FuZF9zcGVjaWFsdHkuY3N2IikgJT4lIGphbml0b3I6OmNsZWFuX25hbWVzKCkNCg0KYmVkcyAlPiUgDQptdXRhdGUoZGF0ZSA9IHlxKHF1YXJ0ZXIpLA0KICAgICAgICAgeWVhciA9IHllYXIoZGF0ZSkpDQpgYGANCg0KDQpgYGB7cn0NCiMgYmVkIHBlcmNlbnRhZ2UgYXZhaWxhYmxpdHkgZm9yICJhbGwgYWN1dGUiDQojIFdpbGwgbmVlZCB0byBhZGQgZmlsdGVyIGZvciB5ZWFyIGJhc2VkIG9uIHVzZXIgaW5wdXQNCmJlZHNfcGxvdGx5IDwtIGJlZHMgJT4lDQogIGZpbHRlcihzcGVjaWFsdHlfbmFtZSA9PSAiQWxsIEFjdXRlIikgJT4lIA0KICBncm91cF9ieShxdWFydGVyLCBzcGVjaWFsdHlfbmFtZSkgJT4lDQogIHN1bW1hcmlzZShtZWFuX3BlcmNfb2NjID0gbWVhbihwZXJjZW50YWdlX29jY3VwYW5jeSkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gcXVhcnRlciwgeSA9IG1lYW5fcGVyY19vY2MpKSsNCiAgZ2VvbV9saW5lKGFlcyhjb2xvdXIgPSBzcGVjaWFsdHlfbmFtZSwgZ3JvdXAgPSBzcGVjaWFsdHlfbmFtZSkpKw0KICBnZW9tX3BvaW50KHNpemUgPSAwLjUpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKSsNCiAgbGFicyh0aXRsZSA9ICJNZWFuIGJlZCBhdmFpbGFiaWxpdHkgZm9yIGFsbCBBY3V0ZSBQYXRpZW50cyIsDQogICAgICAgeCA9ICJcblllYXIgYW5kIFF1YXJ0ZXIiLA0KICAgICAgIHkgPSAiQXZlcmFnZSBQZXJjZW50YWdlIE9jY3VwYW5jeSIpDQoNCmdncGxvdGx5KGJlZHNfcGxvdGx5KSAlPiUgY29uZmlnKGRpc3BsYXlNb2RlQmFyID0gRkFMU0UpDQogIA0KDQpgYGANCg0KIyMgU2NvdGxhbmQgU2hhcGVmaWxlDQojIyMjIGFlX3dhaXRfdGltZXMgd3JhbmdsaW5nDQpgYGB7cn0NCmFlX3dhaXRfdGltZXMgPC0gcmVhZF9jc3YoInJhd19kYXRhL25vbl9jb3ZpZF9yYXdfZGF0YS9tb250aGx5X2FlX3dhaXRpbmd0aW1lc18yMDIyMDYuY3N2IikgJT4lIGphbml0b3I6OmNsZWFuX25hbWVzKCkNCg0KI2dsaW1wc2UoYWVfd2FpdF90aW1lcykNCg0KDQojbWFrZSBhIGRhdGUgYW5kIHllYXIgY29sdW1uIHdpdGggdGhlIGZpcnN0IGRhdGUgb2YgZXZlcnkgbW9udGgNCmFlX3dhaXRfdGltZXMgPC0gYWVfd2FpdF90aW1lcyAlPiUgDQogIG11dGF0ZShkYXRlID0geW0obW9udGgpLCAuYWZ0ZXIgPSBtb250aCwNCiAgICAgICAgIHllYXIgPSB5ZWFyKGRhdGUpKQ0KDQojbWFrZSBhIHBlcmNlbnQgY29sdW1uIHdpdGggcGVyY2VudCBvZiBwYXRpZW50cyBtZWV0aW5nIHRoZSA0aHIgdGFyZ2V0IHRpbWUNCmFlX3dhaXRfdGltZXMgPC0gYWVfd2FpdF90aW1lcyAlPiUgDQogIG11dGF0ZShwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQgPSAobnVtYmVyX21lZXRpbmdfdGFyZ2V0X2FnZ3JlZ2F0ZS9udW1iZXJfb2ZfYXR0ZW5kYW5jZXNfYWdncmVnYXRlKSoxMDApDQoNCnRhcmdldF8yMDA3IDwtIGFlX3dhaXRfdGltZXMgJT4lDQogIGdyb3VwX2J5KHllYXIsIGhidCkgJT4lIA0KICBzdW1tYXJpc2UoYWVfNGhyX3RhcmdldF9hY2hpZXZlZCA9IG1lYW4ocGVyY2VudF80aHJfdGFyZ2V0X2FjaGlldmVkLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIGZpbHRlcih5ZWFyID09IDIwMDcpICU+JSANCiAgcmVuYW1lKGFlX3RhcmdldF8yMDA3ID0gYWVfNGhyX3RhcmdldF9hY2hpZXZlZCkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBzZWxlY3QoaGJ0LGFlX3RhcmdldF8yMDA3KQ0KDQp0YXJnZXRfMjAwOCA8LSBhZV93YWl0X3RpbWVzICU+JQ0KICBncm91cF9ieSh5ZWFyLCBoYnQpICU+JSANCiAgc3VtbWFyaXNlKGFlXzRocl90YXJnZXRfYWNoaWV2ZWQgPSBtZWFuKHBlcmNlbnRfNGhyX3RhcmdldF9hY2hpZXZlZCwgbmEucm0gPSBUUlVFKSkgJT4lIA0KICBmaWx0ZXIoeWVhciA9PSAyMDA4KSAlPiUgDQogIHJlbmFtZShhZV90YXJnZXRfMjAwOCA9IGFlXzRocl90YXJnZXRfYWNoaWV2ZWQpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgc2VsZWN0KGhidCxhZV90YXJnZXRfMjAwOCkNCg0KdGFyZ2V0XzIwMDkgPC0gYWVfd2FpdF90aW1lcyAlPiUNCiAgZ3JvdXBfYnkoeWVhciwgaGJ0KSAlPiUgDQogIHN1bW1hcmlzZShhZV80aHJfdGFyZ2V0X2FjaGlldmVkID0gbWVhbihwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQsIG5hLnJtID0gVFJVRSkpICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAwOSkgJT4lIA0KICByZW5hbWUoYWVfdGFyZ2V0XzIwMDkgPSBhZV80aHJfdGFyZ2V0X2FjaGlldmVkKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdChoYnQsYWVfdGFyZ2V0XzIwMDkpDQoNCnRhcmdldF8yMDEwIDwtIGFlX3dhaXRfdGltZXMgJT4lDQogIGdyb3VwX2J5KHllYXIsIGhidCkgJT4lIA0KICBzdW1tYXJpc2UoYWVfNGhyX3RhcmdldF9hY2hpZXZlZCA9IG1lYW4ocGVyY2VudF80aHJfdGFyZ2V0X2FjaGlldmVkLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIGZpbHRlcih5ZWFyID09IDIwMTApICU+JSANCiAgcmVuYW1lKGFlX3RhcmdldF8yMDEwID0gYWVfNGhyX3RhcmdldF9hY2hpZXZlZCkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBzZWxlY3QoaGJ0LGFlX3RhcmdldF8yMDEwKQ0KDQp0YXJnZXRfMjAxMSA8LSBhZV93YWl0X3RpbWVzICU+JQ0KICBncm91cF9ieSh5ZWFyLCBoYnQpICU+JSANCiAgc3VtbWFyaXNlKGFlXzRocl90YXJnZXRfYWNoaWV2ZWQgPSBtZWFuKHBlcmNlbnRfNGhyX3RhcmdldF9hY2hpZXZlZCwgbmEucm0gPSBUUlVFKSkgJT4lIA0KICBmaWx0ZXIoeWVhciA9PSAyMDExKSAlPiUgDQogIHJlbmFtZShhZV90YXJnZXRfMjAxMSA9IGFlXzRocl90YXJnZXRfYWNoaWV2ZWQpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgc2VsZWN0KGhidCxhZV90YXJnZXRfMjAxMSkNCg0KdGFyZ2V0XzIwMTIgPC0gYWVfd2FpdF90aW1lcyAlPiUNCiAgZ3JvdXBfYnkoeWVhciwgaGJ0KSAlPiUgDQogIHN1bW1hcmlzZShhZV80aHJfdGFyZ2V0X2FjaGlldmVkID0gbWVhbihwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQsIG5hLnJtID0gVFJVRSkpICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAxMikgJT4lIA0KICByZW5hbWUoYWVfdGFyZ2V0XzIwMTIgPSBhZV80aHJfdGFyZ2V0X2FjaGlldmVkKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdChoYnQsYWVfdGFyZ2V0XzIwMTIpDQoNCnRhcmdldF8yMDEzIDwtIGFlX3dhaXRfdGltZXMgJT4lDQogIGdyb3VwX2J5KHllYXIsIGhidCkgJT4lIA0KICBzdW1tYXJpc2UoYWVfNGhyX3RhcmdldF9hY2hpZXZlZCA9IG1lYW4ocGVyY2VudF80aHJfdGFyZ2V0X2FjaGlldmVkLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIGZpbHRlcih5ZWFyID09IDIwMTMpICU+JSANCiAgcmVuYW1lKGFlX3RhcmdldF8yMDEzID0gYWVfNGhyX3RhcmdldF9hY2hpZXZlZCkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBzZWxlY3QoaGJ0LGFlX3RhcmdldF8yMDEzKQ0KDQp0YXJnZXRfMjAxNCA8LSBhZV93YWl0X3RpbWVzICU+JQ0KICBncm91cF9ieSh5ZWFyLCBoYnQpICU+JSANCiAgc3VtbWFyaXNlKGFlXzRocl90YXJnZXRfYWNoaWV2ZWQgPSBtZWFuKHBlcmNlbnRfNGhyX3RhcmdldF9hY2hpZXZlZCwgbmEucm0gPSBUUlVFKSkgJT4lIA0KICBmaWx0ZXIoeWVhciA9PSAyMDE0KSAlPiUgDQogIHJlbmFtZShhZV90YXJnZXRfMjAxNCA9IGFlXzRocl90YXJnZXRfYWNoaWV2ZWQpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgc2VsZWN0KGhidCxhZV90YXJnZXRfMjAxNCkNCg0KdGFyZ2V0XzIwMTUgPC0gYWVfd2FpdF90aW1lcyAlPiUNCiAgZ3JvdXBfYnkoeWVhciwgaGJ0KSAlPiUgDQogIHN1bW1hcmlzZShhZV80aHJfdGFyZ2V0X2FjaGlldmVkID0gbWVhbihwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQsIG5hLnJtID0gVFJVRSkpICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAxNSkgJT4lIA0KICByZW5hbWUoYWVfdGFyZ2V0XzIwMTUgPSBhZV80aHJfdGFyZ2V0X2FjaGlldmVkKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdChoYnQsYWVfdGFyZ2V0XzIwMTUpDQoNCnRhcmdldF8yMDE2IDwtIGFlX3dhaXRfdGltZXMgJT4lDQogIGdyb3VwX2J5KHllYXIsIGhidCkgJT4lIA0KICBzdW1tYXJpc2UoYWVfNGhyX3RhcmdldF9hY2hpZXZlZCA9IG1lYW4ocGVyY2VudF80aHJfdGFyZ2V0X2FjaGlldmVkLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIGZpbHRlcih5ZWFyID09IDIwMTYpICU+JSANCiAgcmVuYW1lKGFlX3RhcmdldF8yMDE2ID0gYWVfNGhyX3RhcmdldF9hY2hpZXZlZCkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBzZWxlY3QoaGJ0LGFlX3RhcmdldF8yMDE2KQ0KDQp0YXJnZXRfMjAxNyA8LSBhZV93YWl0X3RpbWVzICU+JQ0KICBncm91cF9ieSh5ZWFyLCBoYnQpICU+JSANCiAgc3VtbWFyaXNlKGFlXzRocl90YXJnZXRfYWNoaWV2ZWQgPSBtZWFuKHBlcmNlbnRfNGhyX3RhcmdldF9hY2hpZXZlZCwgbmEucm0gPSBUUlVFKSkgJT4lIA0KICBmaWx0ZXIoeWVhciA9PSAyMDE3KSAlPiUgDQogIHJlbmFtZShhZV90YXJnZXRfMjAxNyA9IGFlXzRocl90YXJnZXRfYWNoaWV2ZWQpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgc2VsZWN0KGhidCxhZV90YXJnZXRfMjAxNykNCg0KdGFyZ2V0XzIwMTggPC0gYWVfd2FpdF90aW1lcyAlPiUNCiAgZ3JvdXBfYnkoeWVhciwgaGJ0KSAlPiUgDQogIHN1bW1hcmlzZShhZV80aHJfdGFyZ2V0X2FjaGlldmVkID0gbWVhbihwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQsIG5hLnJtID0gVFJVRSkpICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAxOCkgJT4lIA0KICByZW5hbWUoYWVfdGFyZ2V0XzIwMTggPSBhZV80aHJfdGFyZ2V0X2FjaGlldmVkKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdChoYnQsYWVfdGFyZ2V0XzIwMTgpDQoNCnRhcmdldF8yMDE5IDwtIGFlX3dhaXRfdGltZXMgJT4lDQogIGdyb3VwX2J5KHllYXIsIGhidCkgJT4lIA0KICBzdW1tYXJpc2UoYWVfNGhyX3RhcmdldF9hY2hpZXZlZCA9IG1lYW4ocGVyY2VudF80aHJfdGFyZ2V0X2FjaGlldmVkLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIGZpbHRlcih5ZWFyID09IDIwMTkpICU+JSANCiAgcmVuYW1lKGFlX3RhcmdldF8yMDE5ID0gYWVfNGhyX3RhcmdldF9hY2hpZXZlZCkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBzZWxlY3QoaGJ0LGFlX3RhcmdldF8yMDE5KQ0KDQp0YXJnZXRfMjAyMCA8LSBhZV93YWl0X3RpbWVzICU+JQ0KICBncm91cF9ieSh5ZWFyLCBoYnQpICU+JSANCiAgc3VtbWFyaXNlKGFlXzRocl90YXJnZXRfYWNoaWV2ZWQgPSBtZWFuKHBlcmNlbnRfNGhyX3RhcmdldF9hY2hpZXZlZCwgbmEucm0gPSBUUlVFKSkgJT4lIA0KICBmaWx0ZXIoeWVhciA9PSAyMDIwKSAlPiUgDQogIHJlbmFtZShhZV90YXJnZXRfMjAyMCA9IGFlXzRocl90YXJnZXRfYWNoaWV2ZWQpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgc2VsZWN0KGhidCxhZV90YXJnZXRfMjAyMCkNCg0KdGFyZ2V0XzIwMjEgPC0gYWVfd2FpdF90aW1lcyAlPiUNCiAgZ3JvdXBfYnkoeWVhciwgaGJ0KSAlPiUgDQogIHN1bW1hcmlzZShhZV80aHJfdGFyZ2V0X2FjaGlldmVkID0gbWVhbihwZXJjZW50XzRocl90YXJnZXRfYWNoaWV2ZWQsIG5hLnJtID0gVFJVRSkpICU+JSANCiAgZmlsdGVyKHllYXIgPT0gMjAyMSkgJT4lIA0KICByZW5hbWUoYWVfdGFyZ2V0XzIwMjEgPSBhZV80aHJfdGFyZ2V0X2FjaGlldmVkKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIHNlbGVjdChoYnQsYWVfdGFyZ2V0XzIwMjEpDQogIA0KYGBgDQoNCiMjIyMgc2hhcGUgZmlsZSB3cmFuZ2xpbmcNCmBgYHtyfQ0Kc2NvdGxhbmQgPC0gc3RfcmVhZCgiLi4vU0dfTkhTX0hlYWx0aEJvYXJkc18yMDE5X3NoYXBlZmlsZS9TR19OSFNfSGVhbHRoQm9hcmRzXzIwMTkuc2hwIikNCg0KIyBtYWtlIGEgc21hbGxlciB2ZXJzaW9uIGZvciBwZXJmb3JtYW5jZSBpc3N1ZXMNCnNjb3RsYW5kX3NtYWxsZXIgPC0gc2NvdGxhbmQgJT4lIA0KICBzdF9zaW1wbGlmeShUUlVFLCBkVG9sZXJhbmNlID0gMjAwMCkNCiNmaXhlcyBwcm9ibGVtcyBjYXVzZWQgYnkgYWJvdmUgDQpzY290bGFuZF9zbWFsbGVyIDwtIHNmOjpzdF9jYXN0KHNjb3RsYW5kX3NtYWxsZXIsICJNVUxUSVBPTFlHT04iKQ0KDQojYWRkIGluIHRoZSBBJkUgNCBociB0YXJnZXQgZGF0YSBmb3IgZWFjaCB5ZWFyDQpzY290bGFuZF9zbWFsbGVyIDwtICBzY290bGFuZF9zbWFsbGVyICU+JSANCiAgbXV0YXRlKGNlbnRyZXMgPSBzdF9jZW50cm9pZChzdF9tYWtlX3ZhbGlkKGdlb21ldHJ5KSkpICU+JQ0KICAgIG11dGF0ZShsYXQgPSBzdF9jb29yZGluYXRlcyhjZW50cmVzKVssMV0sDQogICAgICAgICAgIGxvbmcgPSBzdF9jb29yZGluYXRlcyhjZW50cmVzKVssMl0sDQogICAgICAgICAgIHRhcmdldF8yMDA3ID0gdGFyZ2V0XzIwMDckYWVfdGFyZ2V0XzIwMDcsDQogICAgICAgICAgIHRhcmdldF8yMDA4ID0gdGFyZ2V0XzIwMDgkYWVfdGFyZ2V0XzIwMDgsDQogICAgICAgICAgIHRhcmdldF8yMDA5ID0gdGFyZ2V0XzIwMDkkYWVfdGFyZ2V0XzIwMDksDQogICAgICAgICAgIHRhcmdldF8yMDEwID0gdGFyZ2V0XzIwMTAkYWVfdGFyZ2V0XzIwMTAsDQogICAgICAgICAgIHRhcmdldF8yMDExID0gdGFyZ2V0XzIwMTEkYWVfdGFyZ2V0XzIwMTEsDQogICAgICAgICAgIHRhcmdldF8yMDEyID0gdGFyZ2V0XzIwMTIkYWVfdGFyZ2V0XzIwMTIsDQogICAgICAgICAgIHRhcmdldF8yMDEzID0gdGFyZ2V0XzIwMTMkYWVfdGFyZ2V0XzIwMTMsDQogICAgICAgICAgIHRhcmdldF8yMDE0ID0gdGFyZ2V0XzIwMTQkYWVfdGFyZ2V0XzIwMTQsDQogICAgICAgICAgIHRhcmdldF8yMDE1ID0gdGFyZ2V0XzIwMTUkYWVfdGFyZ2V0XzIwMTUsDQogICAgICAgICAgIHRhcmdldF8yMDE2ID0gdGFyZ2V0XzIwMTYkYWVfdGFyZ2V0XzIwMTYsDQogICAgICAgICAgIHRhcmdldF8yMDE3ID0gdGFyZ2V0XzIwMTckYWVfdGFyZ2V0XzIwMTcsDQogICAgICAgICAgIHRhcmdldF8yMDE4ID0gdGFyZ2V0XzIwMTgkYWVfdGFyZ2V0XzIwMTgsDQogICAgICAgICAgIHRhcmdldF8yMDE5ID0gdGFyZ2V0XzIwMTkkYWVfdGFyZ2V0XzIwMTksDQogICAgICAgICAgIHRhcmdldF8yMDIwID0gdGFyZ2V0XzIwMjAkYWVfdGFyZ2V0XzIwMjAsDQogICAgICAgICAgIHRhcmdldF8yMDIxID0gdGFyZ2V0XzIwMjEkYWVfdGFyZ2V0XzIwMjENCiAgICAgICAgICAgICAgICAgICkNCg0KDQojIFRoaXMgd2lsbCByZXF1aXJlIGZpbHRlcmVkIGJ5IHRoZSB5ZWFyIHNlbGVjdGVkIGluIHRoZSBkYXNoYm9hcmQNCiMgQ2FuIHdlIGdldCB0aGUgYnV0dG9uIG9yIGRyb3Bkb3duIHRvIHBhc3MgZWcgInRhcmdldF8yMDE2IiB0byB0aGlzIGluIDIgcGxhY2VzPw0KcCA8LSBnZ3Bsb3Qoc2NvdGxhbmRfc21hbGxlcikgKyANCiAgZ2VvbV9zZihhZXMoZmlsbCA9IHRhcmdldF8yMDIxLCANCiAgICAgICAgICAgICAgdGV4dCA9IHBhc3RlKCI8Yj4iLCBIQk5hbWUsICI8L2I+XG4iLCByb3VuZCh0YXJnZXRfMjAyMSwgZGlnaXRzID0gMiksIiUiLCBzZXAgPSAiIikpKSArIA0KICBzY2FsZV9maWxsX3ZpcmlkaXNfYyhvcHRpb24gPSAicGxhc21hIiwgbmFtZSA9ICI0SHIgQSZFIFRhcmdldCAlIikrDQogIHRoZW1lX3ZvaWQoKSsNCiAgbGFicyh0aXRsZSA9ICJQZXJjZW50IG9mIEEmRSBkZXB0cyBtYWtpbmcgdGhlIDRociB0YXJnZXQiKQ0KDQpwICU+JQ0KICBnZ3Bsb3RseSh0b29sdGlwID0gInRleHQiKSAlPiUNCiAgc3R5bGUoaG92ZXJsYWJlbCA9IGxpc3QoYmdjb2xvciA9ICJ3aGl0ZSIpLCBob3Zlcm9uID0gImZpbGwiKSU+JSANCiAgY29uZmlnKGRpc3BsYXlNb2RlQmFyID0gRkFMU0UpDQpgYGANCg0KIyMgU0lNRCBncmFwaCANCg0KYGBge3J9DQpzaW1kIDwtIHJlYWRfY3N2KCJyYXdfZGF0YS9ub25fY292aWRfcmF3X2RhdGEvaW5wYXRpZW50X2FuZF9kYXljYXNlX2J5X25oc19ib2FyZF9vZl90cmVhdG1lbnRfYW5kX3NpbWQuY3N2IikgJT4lIGphbml0b3I6OmNsZWFuX25hbWVzKCkNCmBgYA0KDQpgYGB7cn0NCiMgYXZlcmFnZSBlcGlzb2RlcyBieSBTSU1EIHZhbHVlDQojIGN1cnJlbnRseSB1bmZpbHRlcmVkIGZvciBoZWFsdGggYm9hcmQgb3IgYWRtaXNzaW9uIHR5cGUgZXRjDQpzaW1kX3Bsb3RseSA8LSBzaW1kICU+JSANCiAgZHJvcF9uYShzaW1kKSAlPiUNCiAgbXV0YXRlKHNpbWQgPSBhcy5mYWN0b3Ioc2ltZCkpICU+JSAjIGdpdmVzIGVhY2ggc2ltZCBhIHNlcGFyYXRlIGNvbG91cg0KICBncm91cF9ieShxdWFydGVyLCBzaW1kKSAlPiUgDQogIHN1bW1hcmlzZShhdmdfZXBpc29kZXMgPSBtZWFuKGVwaXNvZGVzLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IHF1YXJ0ZXIsIHkgPSBhdmdfZXBpc29kZXMsIGdyb3VwID0gc2ltZCkpKw0KICBnZW9tX2xpbmUoYWVzKGNvbG91ciA9IHNpbWQpKSsNCiAgZ2VvbV9wb2ludChzaXplID0gMC41KSsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpKw0KICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgSG9zcGl0YWwgRXBpc29kZXMgYnkgU0lNRCBEZXByZXZhdGlvbiBzY29yZVxuIiwNCiAgICAgICB4ID0gIlxuWWVhciBhbmQgUXVhcnRlciIsDQogICAgICAgeSA9ICJBdmVyYWdlIEVwaXNvZGVzXG4iKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KDQpnZ3Bsb3RseShzaW1kX3Bsb3RseSkgJT4lIA0KICBjb25maWcoZGlzcGxheU1vZGVCYXIgPSBGQUxTRSkNCmBgYA0KDQojIyBBZ2UgR3JhcGgNCg0KYGBge3J9DQphZ2Vfc2V4IDwtIHJlYWRfY3N2KCJyYXdfZGF0YS9ub25fY292aWRfcmF3X2RhdGEvaW5wYXRpZW50X2FuZF9kYXljYXNlX2J5X25oc19ib2FyZF9vZl90cmVhdG1lbnRfYWdlX2FuZF9zZXguY3N2IikgJT4lIGphbml0b3I6OmNsZWFuX25hbWVzKCkNCg0KDQogIyBhZ2Vfc2V4IDwtICBhZ2Vfc2V4ICU+JSANCiAjICAgIG11dGF0ZShxdWFydGVyID0geXEocXVhcnRlcikpDQpgYGANCg0KYGBge3J9DQojIEF2ZXJhZ2UgbnVtYmVyIG9mIGVwaXNvZGUgZm9yIGFnZSBncm91cHMNCiMgY3VycmVudGx5IHVuZmlsdGVyZWQgYnkgZGVwYXJ0bWVudCBvciBhbnl0aGluZyBlbHNlDQphZ2VfcGxvdGx5IDwtIGFnZV9zZXggJT4lIA0KICBncm91cF9ieShxdWFydGVyLCBhZ2UpICU+JSANCiAgc3VtbWFyaXNlKGF2Z19lcGlzb2RlcyA9IG1lYW4oZXBpc29kZXMsIG5hLnJtID0gVFJVRSkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gcXVhcnRlciwgeSA9IGF2Z19lcGlzb2RlcykpKw0KICBnZW9tX2xpbmUoYWVzKGNvbG91ciA9IGFnZSwgZ3JvdXAgPSBhZ2UpKSsgDQogIGdlb21fcG9pbnQoc2l6ZSA9IDAuNSkrDQogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBIb3NwaXRhbCBFcGlzb2RlcyBieSBBZ2UgR3JvdXBzXG4iLA0KICAgICAgIHggPSAiXG5ZZWFyIGFuZCBRdWFydGVyIiwNCiAgICAgICB5ID0gIkF2ZXJhZ2UgRXBpc29kZXNcbiIpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQogIA0KZ2dwbG90bHkoYWdlX3Bsb3RseSkgJT4lIA0KICBjb25maWcoZGlzcGxheU1vZGVCYXIgPSBGQUxTRSkNCmBgYA0KDQojIyBHZW5kZXINCg0KYGBge3J9DQpzZXhfcGxvdGx5IDwtIGFnZV9zZXggJT4lIA0KICBncm91cF9ieShxdWFydGVyLCBzZXgpICU+JSANCiAgc3VtbWFyaXNlKGF2Z19sZW5ndGhfb2ZfZXBpc29kZSA9IG1lYW4oYXZlcmFnZV9sZW5ndGhfb2ZfZXBpc29kZSwgbmEucm0gPSBUUlVFKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBxdWFydGVyLCB5ID0gYXZnX2xlbmd0aF9vZl9lcGlzb2RlKSkrDQogIGdlb21fbGluZShhZXMoY29sb3VyID0gc2V4LCBncm91cCA9IHNleCkpKw0KICAjZ2VvbV9zbW9vdGgoYWVzKGNvbG91ciA9IHNleCwgZ3JvdXAgPSBzZXgpLCBzZSA9IEZBTFNFKSsNCiAgZ2VvbV9wb2ludChzaXplID0gMC41KSsNCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEhvc3BpdGFsIEVwaXNvZGVzIGJ5IEdlbmRlclxuIiwNCiAgICAgICB4ID0gIlxuWWVhciBhbmQgUXVhcnRlciIsDQogICAgICAgeSA9ICJBdmVyYWdlIEVwaXNvZGVzXG4iKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSsNCiAgDQoNCmdncGxvdGx5KHNleF9wbG90bHksIGhvdmVydGVtcGxhdGUgPSApICU+JSANCiAgY29uZmlnKGRpc3BsYXlNb2RlQmFyID0gRkFMU0UpDQpgYGANCg0K